<template>
    <div class="containers">
      <div class="canvas" id="js-canvas"></div>
      <div class="panel" id="js-properties-panel"></div>
      <ul class="buttons">
        <li>
          <a @click="downloadDiagram($event)">BPMN</a>
        </li>
        <li>
          <a @click="downloadSvg($event)">SVG</a>
        </li>
        <li>
          <a  @click="handlerUndo">撤销</a>
        </li>
        <li>
          <a @click="handlerRedo">恢复</a>
        </li>
        <li>
          <a @click="handlerZoom(0.1)">放大</a>
        </li>
        <li>
          <a @click="handlerZoom(-0.1)">缩小</a>
        </li>
        <li>
          <a  @click="handlerZoom(0)">还原</a>
        </li>
      </ul>
    </div>
</template>

<script>

import { onMounted, reactive, toRefs } from 'vue'
import BpmnModeler from 'bpmn-js/lib/Modeler'
import { xmlStr } from '../mock/xmlStrViewer'
import { BpmnPropertiesPanelModule } from 'bpmn-js-properties-panel'
import magicPropertiesProviderModule from '../provider/magic'
import magicModelDescriptor from '../descriptors/magic'
import { debounce } from 'min-dash'

export default {
  name: 'BpmnProperty',
  setup () {
    const state = reactive({
      xmlStr: '',
      bpmnModeler: null,
      svg: '',
      xml: '',
      canvas: null
    })
    onMounted(() => {
      state.xmlStr = xmlStr
      init()
    })

    const exportArtifacts = debounce(async function () {
      try {
        const { svg } = await state.bpmnModeler.saveSVG()
        state.svg = encodeURIComponent(svg)
      } catch (err) {
        state.svg = ''
      }
      try {
        const { xml } = await state.bpmnModeler.saveXML({ format: true })
        state.xml = encodeURIComponent(xml)
      } catch (err) {
        state.xml = ''
      }
    }, 500)

    const init = () => {
      state.bpmnModeler = new BpmnModeler({
        container: '#js-canvas',
        propertiesPanel: {
          parent: '#js-properties-panel'
        },
        additionalModules: [
          {
            // 禁用左侧面板
            paletteProvider: ['value', ''],

            // 禁用滚轮滚动
            zoomScroll: ['value', ''],
            // 禁止拖动线
            bendpoints: ['value', ''],

            // 禁止点击节点出现contextPad
            contextPadProvider: ['value', ''],
            // 禁止双击节点出现label编辑框
            labelEditingProvider: ['value', '']
          },
          BpmnPropertiesPanelModule,
          magicPropertiesProviderModule
        ],
        moddleExtensions: {
          magic: magicModelDescriptor
        }
      })

      state.bpmnModeler.importXML(state.xmlStr).then(function (result) {
        const { warnings } = result
        console.log('success !', warnings)
        state.canvas = state.bpmnModeler.get('canvas')
        state.canvas.zoom('fit-viewport', 'auto')

        // 标记颜色（1）
        markColor1()
        // 标记颜色（2）
        markColor2()
        // 标记颜色（3）---延迟且无法点击
        markColor3()
        // 绑定流程设计变化事件
        state.bpmnModeler.on('commandStack.changed', exportArtifacts)
      }).catch(function (err) {
        const { warnings, message } = err
        console.log('something went wrong:', warnings, message)
      })
    }

    const markColor1 = () => {
      console.log('标记颜色（1）')
      state.canvas.addMarker('Activity_1w1vj9r', 'highlight')
    }

    const markColor2 = () => {
      console.log('标记颜色（2）')
      const modeling = state.bpmnModeler.get('modeling')
      const elementRegistry = state.bpmnModeler.get('elementRegistry')
      var shape = elementRegistry.get('Activity_1149ksn')
      modeling.setColor([shape], {
        stroke: 'green',
        fill: 'red'
      })
    }

    const markColor3 = () => {
      console.log('标记颜色（3）')
      const overlays = state.bpmnModeler.get('overlays')
      const elementRegistry = state.bpmnModeler.get('elementRegistry')
      const shape2 = elementRegistry.get('Activity_17lsppc')
      const layDiv = '<div class="highlight-overlay" style="width: ' + shape2.width + 'px;height: ' + shape2.height + 'px"></div>'
      overlays.add(shape2.id, {
        position: {
          top: 0,
          left: 0
        },
        html: layDiv
      })
    }

    const downloadDiagram = (e) => {
      console.log('e', e)
      e.currentTarget.href = 'data:application/bpmn20-xml;charset=UTF-8,' + state.xml
      e.currentTarget.download = 'diagram.bpmn'
    }

    const downloadSvg = (e) => {
      e.currentTarget.href = 'data:application/bpmn20-xml;charset=UTF-8,' + state.svg
      e.currentTarget.download = 'diagram.svg'
    }

    const handlerRedo = () => {
      state.bpmnModeler.get('commandStack').redo()
    }
    const handlerUndo = () => {
      state.bpmnModeler.get('commandStack').undo()
    }
    const handlerZoom = (radio) => {
      const newScale = !radio ? 1.0 : state.scale + radio
      state.canvas.zoom(newScale)
      state.scale = newScale
    }

    return {
      ...toRefs(state),
      downloadDiagram,
      downloadSvg,
      handlerRedo,
      handlerUndo,
      handlerZoom
    }
  }
}
</script>
<style scoped>
  .containers {
    background: white;
    overflow: auto;
    background-image: linear-gradient(
      90deg,
      rgba(220, 220, 220, 0.5) 6%,
      transparent 0
    ),
    linear-gradient(rgba(192, 192, 192, 0.5) 6%, transparent 0);
    background-size: 12px 12px;
    width: 100%;
    height: calc(100vh - 60px);
    -webkit-tap-highlight-color: rgba(255, 255, 255, 0);
  }
  .canvas {
    width: 100%;
    height: 100%;
  }
  .panel {
    position: absolute;
    right: 0;
    top: 110px;
    width: 300px;
  }
  .buttons {
    position: absolute;
    left: 20px;
    bottom: 20px;
  }
  .buttons li {
    display: inline-block;
    margin: 5px;
  }
  .buttons li a {
    color: #333;
    background: #fff;
    cursor: pointer;
    padding: 8px;
    border: 1px solid #ccc;
    text-decoration: none;
  }
</style>
